//
//	File: OyMath3D.h
//
#ifndef OYMATH3D_H
#define OYMATH3D_H

#include <math.h>

#ifndef NULL
#define NULL 0
#endif

#if defined(_USRDLL)
#define DllExport __declspec(dllexport)
#else
#define DllExport
#endif

const double OY_PI  = 3.14159265;
const float OY_2PI	= 6.283185f;


#define OY_FRONT    0
#define OY_BACK     1
#define OY_PLANAR   2
#define OY_CLIPPED  3
#define OY_CULLED   4
#define OY_VISIBLE  5


class OyMatrix;
class OyOBB;
class OyAABB;
class OyPlane;
class OyQuaternion;
class OyPolygon;

/**************************************************************************************
      CCCCC     OOOOO              CCCCC   PPPPPPP   UU    UU     
     CC   CC   OO   OO            CC   CC  PP    PP  UU    UU     
    CC        OO     OO          CC        PP    PP  UU    UU     
    CC        OO     OO  yy  yy  CC        PP    PP  UU    UU     
    CC        OO     OO  yy  yy  CC        PP    PP  UU    UU     
    CC        OO     OO  yy  yy  CC        PPPPPPP   UU    UU     
    CC        OO     OO  yy  yy  CC        PP        UU    UU     
    CC        OO     OO   yyyy   CC        PP        UU    UU     
     CC   CC   OO   OO    yyyy    CC   CC  PP        UU    UU     
      CCCCC     OOOOO      yy      CCCCC   PP         UUUUUU      
                           yy                                     
                         yyy                                      
                                                                  
***************************************************************************************/

struct CPUINFO_TYP 
{
	bool bSSE;        // Streaming SIMD Extensions
	bool bSSE2;       // STreaming SIMD Extensions 2
	bool b3DNOW;      // 3DNow! (vendor independant)
	bool b3DNOWEX;    // 3DNow! (AMD specific extensions)
	bool bMMX;        // MMX support
	bool bMMXEX;      // MMX (AMD specific extensions)
	bool bEXT;        // extended features available
	char vendor[13];  // vendor name
	char name[48];    // cpu name
};

class DllExport COyCPU
{
private:

	COyCPU() {}

	//copy ctor and assignment should be private
	COyCPU(const COyCPU&);
	COyCPU& operator=(const COyCPU&);

private:
	CPUINFO_TYP GetCPUInfo();
	bool OSSupportsSSE();
	void GetCPUName(char* chName, int cpuNameStrNum, int BrandID, const char* vendor);

public:
	//this is a singleton
	static COyCPU* GetInstance();
	static bool m_bSSE;

	bool OyMath3DInitCPU(void);	
};



/**************************************************************************************
                                                                                       
      OOOOO            VV    VV                                         444  DDDDDD       
     OO   OO           VV    VV                   tt                    444  DD   DD      
    OO     OO          VV    VV                   tt                   4444  DD    DD     
    OO     OO  yy  yy   VV  VV   eeeee    ccccc  tttt  ooooo   rrrrr   4444  DD    DD     
    OO     OO  yy  yy   VV  VV  ee   ee  cc   cc  tt  oo   oo  rrr    44 44  DD    DD     
    OO     OO  yy  yy   VV  VV  ee   ee  cc       tt  oo   oo  rr     44 44  DD    DD     
    OO     OO  yy  yy    VVVV   eeeeeee  cc       tt  oo   oo  rr    44  44  DD    DD     
    OO     OO   yyyy     VVVV   ee       cc       tt  oo   oo  rr    4444444 DD    DD     
     OO   OO    yyyy      VV    ee   ee  cc   cc  tt  oo   oo  rr        44  DD   DD      
      OOOOO      yy       VV     eeeee    ccccc    tt  ooooo   rr        44  DDDDDD       
                 yy                                                                       
               yyy                                                                        
                                                                                          
***************************************************************************************/
// basic 4D vector class
class DllExport OyVector4D
{
public:
	float x, y, z, w;

	//---------------------------------------

	OyVector4D(void)							{ x=0, y=0, z=0, w=1.0f; }
	OyVector4D(float _x, float _y, float _z)	{ x=_x; y=_y; z=_z; w=1.0f; }
	OyVector4D(const float *v)					{ x=*v; y=*(v+1); z=*(v+2); w=1.0f; }
	OyVector4D(const OyVector4D &v)				{ x=v.x; y=v.y; z=v.z; w=v.w; }

	void operator += (const OyVector4D &v);					// operator +=
	void operator -= (const OyVector4D &v);					// operator -=
	void operator *= (float f);								// scale vector
	void operator /= (float f);								// scale down
	void operator += (float f);								// add scalar
	void operator -= (float f);								// subtract scalar
	float			operator * (const OyVector4D &v)const;	// dot product
	OyVector4D		operator * (float f)const;				// scale vector
	OyVector4D		operator / (float f)const;				// scalar divide
	OyVector4D		operator + (float f)const;				// add scalar
	OyVector4D		operator - (float f)const;				// scale down
	OyVector4D		operator - ()const;						// Negative
	//OyQuaternion	operator * (const OyQuaternion &q)const;// vector * quaternion
	OyVector4D operator * (const OyMatrix &m)const;			// vector-matrix product
	OyVector4D operator + (const OyVector4D &v)const;		// addition
	OyVector4D operator - (const OyVector4D &v)const;		// subtraction


	/**
	* rotate the vector with the given matrix, ignoring translation
	* information in matrix if they are present
	*/
	void RotateWith(const OyMatrix &m);

	/**
	* rotate the vector with the inverse rotation part of the given
	* matrix, ignoring translation of the matrix if present.
	*/
	void InvRotateWith(const OyMatrix &m);


	inline void Set(float _x, float _y, float _z, float _w=1.0f) 
	{
		x=_x; y=_y; z=_z; w=_w;
	}

	inline void Set(const OyVector4D &v)
	{
		x=v.x; y=v.y; z=v.z; w=v.w;
	}

	inline float GetSqrLength(void) const
	{
		return (x*x + y*y + z*z); 
	}

	inline float AngleWith(OyVector4D &v)
	{
		return (float)acos( ((*this) * v) / (this->GetLength() * v.GetLength()) );
	}

	inline void Difference(const OyVector4D &v1, const OyVector4D &v2)
	{
		x = v2.x - v1.x;
		y = v2.y - v1.y;
		z = v2.z - v1.z;
		w = 1.0f;
	}

	inline float GetLength(void) 
	{
		float f=0;
		if( !COyCPU::m_bSSE ) 
			f = (float)sqrt(x*x + y*y + z*z);
		else 
		{
			w = 0.0f;
			__asm 
			{
				mov    esi,   this            ; vector u
				movups xmm0,  [esi]           ; first vector in xmm0
				mulps  xmm0,  xmm0            ; mul with 2nd vector
				movaps xmm1,  xmm0            ; copy result
				shufps xmm1,  xmm1, 4Eh       ; shuffle: f1,f0,f3,f2
				addps  xmm0,  xmm1            ; add: f3+f1,f2+f0,f1+f3,f0+f2 
				movaps xmm1,  xmm0            ; copy results
				shufps xmm1,  xmm1, 11h       ; shuffle: f0+f2,f1+f3,f0+f2,f1+f3 
				addps  xmm0,  xmm1            ; add: x,x,f0+f1+f2+f3,f0+f1+f2+f3
				sqrtss xmm0,  xmm0            ; sqroot from least bit value
				movss     f,  xmm0			  ; move result from xmm0 to edi
			}
			w = 1.0f;
		}
		return f;
	}

	inline void Normalize(void)
	{
		if( !COyCPU::m_bSSE ) 
		{
			float f = (float)sqrt(x*x + y*y + z*z);

			if (f != 0.0f)
			{
				x/=f; y/=f; z/=f;
			}
		}
		else 
		{
			w = 0.0f;
			__asm 
			{
				mov    esi,   this            ; vector u
				movups xmm0,  [esi]           ; first vector in xmm0
				movaps xmm2,  xmm0            ; copy original vector
				mulps  xmm0,  xmm0            ; mul with 2nd vector
				movaps xmm1,  xmm0            ; copy result
				shufps xmm1,  xmm1, 4Eh       ; shuffle: f1,f0,f3,f2
				addps  xmm0,  xmm1            ; add: f3+f1,f2+f0,f1+f3,f0+f2 
				movaps xmm1,  xmm0            ; copy results
				shufps xmm1,  xmm1, 11h       ; shuffle: f0+f2,f1+f3,f0+f2,f1+f3 
				addps  xmm0,  xmm1            ; add: x,x,f0+f1+f2+f3,f0+f1+f2+f3
         
				rsqrtps xmm0,  xmm0           ; recip. sqrt (faster than ss + shufps)
				mulps   xmm2,  xmm0           ; mul by reciprocal
				movups  [esi], xmm2           ; bring back result
			}
			w = 1.0f;
		}
	}

	inline void Cross(const OyVector4D &v1, const OyVector4D &v2) 
	{
		if ( !COyCPU::m_bSSE )
		{
			x = v1.y * v2.z - v1.z * v2.y;
			y = v1.z * v2.x - v1.x * v2.z;
			z = v1.x * v2.y - v1.y * v2.x;
			w = 1.0f;
		}
		else 
		{
			__asm 
			{
				mov esi, v1
				mov edi, v2

				movups xmm0, [esi]
				movups xmm1, [edi]
				movaps xmm2, xmm0
				movaps xmm3, xmm1

				shufps xmm0, xmm0, 0xC9
				shufps xmm1, xmm1, 0xD2
				mulps  xmm0, xmm1

				shufps xmm2, xmm2, 0xD2
				shufps xmm3, xmm3, 0xC9
				mulps  xmm2, xmm3

				subps  xmm0, xmm2

				mov    esi, this
				movups [esi], xmm0
			}
			w = 1.0f;
		}
	}
};

/**************************************************************************************
      OOOOO            MM      MM                     ii             
     OO   OO           MM      MM           tt        ii             
    OO     OO          MMM    MMM           tt                       
    OO     OO  yy  yy  MMM    MMM   aaaaa  tttt rrrrr ii  xx  xx     
    OO     OO  yy  yy  MMMM  MMMM  aa   aa  tt  rrr   ii  xx  xx     
    OO     OO  yy  yy  MMMM  MMMM       aa  tt  rr    ii   xxxx      
    OO     OO  yy  yy  MM MMMM MM   aaaaaa  tt  rr    ii    xx       
    OO     OO   yyyy   MM MMMM MM  aa   aa  tt  rr    ii   xxxx      
     OO   OO    yyyy   MM  MM  MM  aa  aaa  tt  rr    ii  xx  xx     
      OOOOO      yy    MM  MM  MM   aaaaaa   tt rr    ii  xx  xx     
                 yy                                                  
               yyy                                                   
***************************************************************************************/
class DllExport OyMatrix 
{
public:
    float _11, _12, _13, _14;
    float _21, _22, _23, _24;
    float _31, _32, _33, _34;
    float _41, _42, _43, _44;

	//---------------------------------------

	OyMatrix(void) {}
	OyMatrix(const float* f);
	OyMatrix operator * (const OyMatrix &m)const;		// matrix multiplication
	//OyVector4D operator * (const OyVector4D &vc)const;	// matrix vector multiplication

	void Identity(void);								// identity matrix
	void RotationX(float a);							// Build rotation matrix around X axis
	void RotationY(float a);							// Build rotation matrix around Y axis
	void RotationZ(float a);							// Build rotation matrix around Z axis
	void RotationXYZ(const OyVector4D &vc);				// x, y and z
	void RotationXYZ(float x, float y, float z);		// x, y and z
	void RotationAxis(const OyVector4D &vcAxis, float a); // Build rotation matrix around arbitrary axis
	void ApplyInverseRotation(OyVector4D *pvc);

	inline void Translate(float dx, float dy, float dz)
	{ _41 = dx;   _42 = dy;   _43 = dz;	}
	inline void SetTranslation(OyVector4D vc, bool EraseContent=false)
	{
		if(EraseContent) 
			Identity();
		_41 = vc.x;		_42 = vc.y;		_43 = vc.z;
	}
	inline OyVector4D GetTranslation(void)	{ return OyVector4D(_41, _42, _43); }

	//void Billboard(OyVector4D vcPos, OyVector4D vcDir, OyVector4D vcWorldUp = OyVector4D(0,1,0));
	//void LookAt(OyVector4D vcPos, OyVector4D vcLookAt, OyVector4D vcWorldUp = OyVector4D(0,1,0));

	void TransposeOf(const OyMatrix &m);			// transpose m, save result in this
	void InverseOf(const OyMatrix &m);				// invert m, save result in this
};

/**************************************************************************************
      OOOOO            RRRRRRR                       
     OO   OO           RR    RR                      
    OO     OO          RR    RR                      
    OO     OO  yy  yy  RR    RR   aaaaa   yy  yy     
    OO     OO  yy  yy  RR    RR  aa   aa  yy  yy     
    OO     OO  yy  yy  RRRRRRR        aa  yy  yy     
    OO     OO  yy  yy  RR    RR   aaaaaa  yy  yy     
    OO     OO   yyyy   RR    RR  aa   aa   yyyy      
     OO   OO    yyyy   RR    RR  aa  aaa   yyyy      
      OOOOO      yy    RR    RR   aaaaaa    yy       
                 yy                         yy       
               yyy                        yyy        
***************************************************************************************/
class DllExport OyRay
{
public:
	OyVector4D m_vcOrig;		// ray origin
	OyVector4D m_vcDir;			// ray direction

	//---------------------------------------

	OyRay(void) { /* nothing to do */ ; }

    inline void Set(OyVector4D vcOrig, OyVector4D vcDir)
	{ 
		m_vcOrig = vcOrig;   m_vcDir  = vcDir; 
	}
    void DeTransform(const OyMatrix &_m);	// transform this ray into matrix space

	// test for intersection with triangle
	// bCull->triangle's back face do not consider
	// t->diatance from ray origion to intersection 
    bool Intersects(const OyVector4D &vc0, const OyVector4D &vc1,
                    const OyVector4D &vc2, bool bCull, float *t);
	// fL->line segment length
    bool Intersects(const OyVector4D &vc0, const OyVector4D &vc1,
                    const OyVector4D &vc2, bool bCull, float fL, float *t);
	// test for intersection with Plane
    bool Intersects(const OyPlane &plane, bool bCull, float *t, OyVector4D *vcHit);       
    bool Intersects(const OyPlane &plane, bool bCull, float fL, float *t, OyVector4D *vcHit);
    // test for intersection with AABB
	bool Intersects(const OyAABB &aabb, float *t);
    bool Intersects(const OyAABB &aabb, float fL, float *t);
	// test for intersection with OBB
    bool Intersects(const OyOBB &obb, float *t);
    bool Intersects(const OyOBB &obb, float fL, float *t);
};

/**************************************************************************************
      OOOOO            PPPPPPP   ll                                
     OO   OO           PP    PP  ll                                
    OO     OO          PP    PP  ll                                
    OO     OO  yy  yy  PP    PP  ll   aaaaa   nnnnnn    eeeee      
    OO     OO  yy  yy  PP    PP  ll  aa   aa  nn   nn  ee   ee     
    OO     OO  yy  yy  PPPPPPP   ll       aa  nn   nn  ee   ee     
    OO     OO  yy  yy  PP        ll   aaaaaa  nn   nn  eeeeeee     
    OO     OO   yyyy   PP        ll  aa   aa  nn   nn  ee          
     OO   OO    yyyy   PP        ll  aa  aaa  nn   nn  ee   ee     
      OOOOO      yy    PP        ll   aaaaaa  nn   nn   eeeee      
                 yy                                                
               yyy                                                 
***************************************************************************************/
class DllExport OyPlane 
{
public:
	OyVector4D	m_vcNormal,		// plane normal vector
				m_vcPoint;		// point on plane
	float		m_fDistance;	// distance to origin

	//---------------------------------------

	OyPlane(void) { /* nothing to do */ ; }

	inline void  Set(const OyVector4D &vcN, const OyVector4D &vcP)
		{ m_fDistance = - ( vcN * vcP); m_vcNormal = vcN; m_vcPoint = vcP; }
	inline void  Set(const OyVector4D &vcN, const OyVector4D &vcP, float fD)
		{ m_vcNormal = vcN; m_fDistance = fD; m_vcPoint = vcP; }

	void  Set(const OyVector4D &v0,  const OyVector4D &v1, const OyVector4D &v2);

	inline float Distance(const OyVector4D &vcPoint)	
		{ return fabs((m_vcNormal*vcPoint) - m_fDistance); }
	
	int   Classify(const OyVector4D &vcPoint);
	int   Classify(const OyPolygon &Polygon);

	// clips a ray into two segments if it intersects the plane
	bool  Clip(const OyRay* _pRay, float fL, OyRay* pFront, OyRay* pBack);

	bool  Intersects(const OyVector4D &vc0, const OyVector4D &vc1, const OyVector4D &vc2);
	// Intersection of two planes?
	bool  Intersects(const OyPlane &plane, OyRay *pIntersection);
	bool  Intersects(const OyAABB &aabb);
	bool  Intersects(const OyOBB &obb);
};

/**************************************************************************************
      OOOOO               AA       AA    BBBBBBB   BBBBBBB      
     OO   OO              AA       AA    BB    BB  BB    BB     
    OO     OO            AAAA     AAAA   BB    BB  BB    BB     
    OO     OO  yy  yy    AAAA     AAAA   BB    BB  BB    BB     
    OO     OO  yy  yy   AA  AA   AA  AA  BBBBBBB   BBBBBBB      
    OO     OO  yy  yy   AA  AA   AA  AA  BB    BB  BB    BB     
    OO     OO  yy  yy   AAAAAA   AAAAAA  BB    BB  BB    BB     
    OO     OO   yyyy   AA    AA AA    AA BB    BB  BB    BB     
     OO   OO    yyyy   AA    AA AA    AA BB    BB  BB    BB     
      OOOOO      yy    AA    AA AA    AA BBBBBBB   BBBBBBB      
                 yy                                             
               yyy                                              
***************************************************************************************/
class DllExport OyAABB
{
public:
	OyVector4D vcMin, vcMax;							// box extreme points
	OyVector4D vcCenter;								// centerpoint

	//---------------------------------------

	OyAABB(void) { /* nothing to do */ ; }
	OyAABB(OyVector4D vcMin, OyVector4D vcMax);

	void Construct(const OyOBB *pObb);                  // build from obb
	int  Cull(const OyPlane *pPlanes, int nNumPlanes);  

	// normals pointing outwards
	void GetPlanes(OyPlane *pPlanes);

	bool Contains(const OyRay &Ray, float fL);
	bool Intersects(const OyRay &Ray, float *t);
	bool Intersects(const OyRay &Ray, float fL, float *t);
	bool Intersects(const OyAABB &aabb);
	bool Intersects(const OyVector4D &vc0);
};

/**************************************************************************************
      OOOOO              OOOOO    BBBBBBB   BBBBBBB      
     OO   OO            OO   OO   BB    BB  BB    BB     
    OO     OO          OO     OO  BB    BB  BB    BB     
    OO     OO  yy  yy  OO     OO  BB    BB  BB    BB     
    OO     OO  yy  yy  OO     OO  BBBBBBB   BBBBBBB      
    OO     OO  yy  yy  OO     OO  BB    BB  BB    BB     
    OO     OO  yy  yy  OO     OO  BB    BB  BB    BB     
    OO     OO   yyyy   OO     OO  BB    BB  BB    BB     
     OO   OO    yyyy    OO   OO   BB    BB  BB    BB     
      OOOOO      yy      OOOOO    BBBBBBB   BBBBBBB      
                 yy                                      
               yyy                                       
***************************************************************************************/
class DllExport OyOBB 
{
public:
	float      fA0,   fA1,  fA2; // half axis length
	OyVector4D vcA0, vcA1, vcA2; // box axis
	OyVector4D vcCenter;         // centerpoint

	//---------------------------------------

	OyOBB(void) { /* nothing to do */ ; }

	inline void DeTransform(const OyOBB &obb, const OyMatrix &m);

	bool Intersects(const OyRay &Ray, float *t);
	bool Intersects(const OyRay &Ray, float fL, float *t);
	bool Intersects(const OyOBB &Obb);
	bool Intersects(const OyVector4D &v0, const OyVector4D &v1, const OyVector4D &v2);

	int  Cull(const OyPlane *pPlanes, int nNumPlanes);      

private:
	void ObbProj(const OyOBB &Obb, const OyVector4D &vcV, float *pfMin, float *pfMax);
	void TriProj(const OyVector4D &v0, const OyVector4D &v1, const OyVector4D &v2, 
				 const OyVector4D &vcV, float *pfMin, float *pfMax);
};

/**************************************************************************************
      OOOOO            PPPPPPP            ll                                        
     OO   OO           PP    PP           ll                                        
    OO     OO          PP    PP           ll                                        
    OO     OO  yy  yy  PP    PP   ooooo   ll  yy  yy   gggggg   ooooo   nnnnnn      
    OO     OO  yy  yy  PP    PP  oo   oo  ll  yy  yy  gg   gg  oo   oo  nn   nn     
    OO     OO  yy  yy  PPPPPPP   oo   oo  ll  yy  yy  gg   gg  oo   oo  nn   nn     
    OO     OO  yy  yy  PP        oo   oo  ll  yy  yy  gg   gg  oo   oo  nn   nn     
    OO     OO   yyyy   PP        oo   oo  ll   yyyy   gg   gg  oo   oo  nn   nn     
     OO   OO    yyyy   PP        oo   oo  ll   yyyy    gggggg  oo   oo  nn   nn     
      OOOOO      yy    PP         ooooo   ll    yy         gg   ooooo   nn   nn     
                 yy                             yy    gg   gg                       
               yyy                            yyy      ggggg                        
                                                                                    
***************************************************************************************/
class DllExport OyPolygon 
{
	friend class OyPlane;      // access for easier classifying

private:
	OyPlane        m_Plane;    // plane which poly lies in

	int            m_NumP;     // number of points
	int            m_NumI;     // number of indices
	OyAABB         m_Aabb;     // bounding box
	unsigned int   m_Flag;     // whatever you want it to be

	void CalcBoundingBox(void);

	//---------------------------------------

public:
	OyPolygon(void);
	~OyPolygon(void);

	//---------------------------------------

	OyVector4D   *m_pPoints;  // list of points
	unsigned int *m_pIndis;   // index list

	void          Set(const OyVector4D *pPoints, int nNumP, const unsigned int *pIndis, int nNumI);

	void          Clip(const OyPlane &Plane, OyPolygon *pFront, OyPolygon *pBack);
	void          Clip(const OyAABB &aabb);
	int           Cull(const OyAABB &aabb);

	void          CopyOf( const OyPolygon &Poly );

	void          SwapFaces(void);

	bool          Intersects(const OyRay &Ray, bool, float *t);
	bool          Intersects(const OyRay &Ray, bool, float fL, float *t);

	int           GetNumPoints(void)      { return m_NumP;    }
	int           GetNumIndis(void)       { return m_NumI;    }
	OyVector4D*   GetPoints(void)         { return m_pPoints; }
	unsigned int* GetIndices(void)        { return m_pIndis;  }
	OyPlane       GetPlane(void)          { return m_Plane;   }
	OyAABB        GetAabb(void)           { return m_Aabb;    }
	unsigned int  GetFlag(void)           { return m_Flag;    }
	void          SetFlag(unsigned int n) { m_Flag = n;       }

};


/**************************************************************************************
      OOOOO              QQQQQ                                                  ii                       
     OO   OO            QQ   QQ                     tt                          ii                       
    OO     OO          QQ     QQ                    tt                                                   
    OO     OO  yy  yy  QQ     QQ  uu   uu   aaaaa  tttt  eeeee   rrrrr nnnnnn   ii   ooooo   nnnnnn      
    OO     OO  yy  yy  QQ     QQ  uu   uu  aa   aa  tt  ee   ee  rrr   nn   nn  ii  oo   oo  nn   nn     
    OO     OO  yy  yy  QQ     QQ  uu   uu       aa  tt  ee   ee  rr    nn   nn  ii  oo   oo  nn   nn     
    OO     OO  yy  yy  QQ     QQ  uu   uu   aaaaaa  tt  eeeeeee  rr    nn   nn  ii  oo   oo  nn   nn     
    OO     OO   yyyy   QQ   QQQQ  uu   uu  aa   aa  tt  ee       rr    nn   nn  ii  oo   oo  nn   nn     
     OO   OO    yyyy    QQ   QQ   uu  uuu  aa  aaa  tt  ee   ee  rr    nn   nn  ii  oo   oo  nn   nn     
      OOOOO      yy      QQQQQQQ   uuuuuu   aaaaaa   tt  eeeee   rr    nn   nn  ii   ooooo   nn   nn     
                 yy                                                                                      
               yyy                                                                                       
***************************************************************************************/
class DllExport OyQuaternion 
{
public:
	float x, y, z, w;

	//---------------------------------------

	OyQuaternion(void)	{ x=0.0f, y=0.0f, z=0.0f, w=1.0f; }
	OyQuaternion(float _x, float _y, float _z, float _w)
						{ x=_x; y=_y; z=_z; w=_w; }

	OyQuaternion& operator = (const OyQuaternion &q) 
			{ x=q.x; y=q.y; z=q.z; w=q.w; return *this; }

	void  MakeFromEuler(float fPitch, float fYaw, float fRoll);
	void  Normalize();
	void  Conjugate(OyQuaternion q);
	void  GetEulers(float *fPitch, float *fYaw, float *fRoll);
	void  GetMatrix(OyMatrix *m);
	
	//float GetMagnitude(void);


	void			operator /= (float f);
	OyQuaternion	operator /  (float f);

	void			operator *= (float f);
	OyQuaternion	operator *  (float f);

	//OyQuaternion	operator *  (const OyVector4D &v) const;

	OyQuaternion	operator *  (const OyQuaternion &q) const;
	void			operator *= (const OyQuaternion &q);

	void			operator += (const OyQuaternion &q);
	OyQuaternion	operator +  (const OyQuaternion &q) const;

	OyQuaternion	operator -	() const { return OyQuaternion(-x, -y, -z, -w); }

	// linear quaternion interpolation
	OyQuaternion&	Lerp		(const OyQuaternion &q2, float t);

	// spherical linear interpolation
	OyQuaternion&	Slerp		(const OyQuaternion &q2, float t);




	//void Rotate(const OyQuaternion &q1, const OyQuaternion &q2);

	//OyVector4D Rotate(const OyVector4D &v);

};

#endif